﻿namespace SchoolSystem.Server.Controllers
{
    using System;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Text;
    using System.Web.Http;
    using System.Web.Http.ValueProviders;
    using SchoolSystem.Data;
    using SchoolSystem.Server.AuthenticationHeaders;
    using SchoolSystem.Server.Models;

    public class AccountsController : BaseApiController<Account>
    {
        private const int TokenLength = 50;
        private const string TokenChars = "qwertyuiopasdfghjklmnbvcxzQWERTYUIOPLKJHGFDSAZXCVBNM";

        [HttpPost]
        [ActionName("token")]
        public HttpResponseMessage LoginUser(AccountLoginModel accountModel)
        {
            return this.ExecuteOperationAndHandleExceptions(() =>
            {
                if (accountModel == null)
                {
                    throw new ArgumentNullException("Invalid account credentials");
                }

                var account = this.data.All()
                                  .FirstOrDefault(a => a.Name == accountModel.Name && 
                                      a.PasswordHash == accountModel.PassowrdHash);
                
                if (account == null)
                {
                    throw new ArgumentException("Invalid username or password");
                }

                if (account.AccessToken == null)
                {
                    account.AccessToken = this.GenerateAccessToken(account.AccountId);
                    this.data.Update(account.AccountId, account);
                }

                var responseModel = new AccountAccessModel()
                {
                    AccessToken = account.AccessToken,
                    AccountType = account.Type
                };
                
                var response = this.Request.CreateResponse(HttpStatusCode.OK, responseModel);
                
                return response;
            });
        }

        [HttpPut]
        [ActionName("logout")]
        public HttpResponseMessage LogoutUser(
            [ValueProvider(typeof(HeaderValueProviderFactory<string>))]
            string accessToken)
        {
            return this.ExecuteOperationAndHandleExceptions(() =>
            {
                var account = this.GetAccountByAccessToken(accessToken);
                account.AccessToken = null;
                this.data.Update(account.AccountId, account);

                var response = this.Request.CreateResponse(HttpStatusCode.NoContent);

                return response;
            });
        }

        private string GenerateAccessToken(int accountId)
        {
            StringBuilder tokenBuilder = new StringBuilder(TokenLength);
            tokenBuilder.Append(accountId);
            
            while (tokenBuilder.Length < TokenLength)
            {
                var index = rand.Next(TokenChars.Length);
                var ch = TokenChars[index];
                tokenBuilder.Append(ch);
            }

            return tokenBuilder.ToString();
        }
    }
}